#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "symtable.h"
Symtable symtable[0x3fff] = {NULL};

unsigned int unsignedinthash_pjw(char *name)
{
    unsigned int val = 0, i;
    for (; *name; ++name)
    {
        val = (val << 2) + *name;
        if (i = val & ~0x3fff)
            val = (val ^ (i >> 12)) & 0x3fff;
    }
    return val;
}

Symbol lookup(char *name)
{
    unsigned int val = unsignedinthash_pjw(name);
    Symtable p = symtable[val];
    //检查是否存在该名
    while (p != NULL)
    {
        if (strcmp(p->sym->name, name))
            p = p->tail;
        else
            break; //有该名，跳出循环
    }
    if (p == NULL)
        return NULL;
    return p->sym;
}

int FindTable(Symbol symbol)
{
    unsigned int val = unsignedinthash_pjw(symbol->name);
    Symtable p = symtable[val];
    //检查是否有同名
    while (p != NULL)
    {
        if (strcmp(p->sym->name, symbol->name))
            p = p->tail;
        else
            break; //有同名，跳出循环比对各属性值是否相同
    }
    //无重名：结束，0表示无冲突
    if (p == NULL)
        return 0;
    return 1;
}

//使用前先查表
void InsertToTable(Symbol symbol)
{
    unsigned int val = unsignedinthash_pjw(symbol->name);
    Symtable p = symtable[val];
    //连入最后
    Symtable node = (Symtable)malloc(sizeof(struct Symtable_));
    node->sym = symbol;
    node->tail = NULL;
    if (p == NULL)
        symtable[val] = node;
    else
    {
        while (p->tail != NULL)
            p = p->tail;
        p->tail = node;
    }
}

//下面的函数用于创建symtable.h中定义的各种结构体
//除Symtbale以外
Type CreateTypeBasic(int basic)
{
    Type p = (Type)malloc(sizeof(struct Type_));
    p->kind = BASIC;
    p->u.basic = basic;
    return p;
}
Type CreateTypeArray(Array array)
{
    Type p = (Type)malloc(sizeof(struct Type_));
    p->kind = ARRAY;
    p->u.array = array;
    return p;
}
Type CreateTypeStructure(Structure structure)
{
    Type p = (Type)malloc(sizeof(struct Type_));
    p->kind = STRUCTURE;
    p->u.structure = structure;
    return p;
}
Array CreateArray(Type elem, int size)
{
    Array p = (Array)malloc(sizeof(struct Array_));
    p->elem = elem;
    p->size = size;
    return p;
}
Structure CreateStructure(FieldList fieldList, char *name)
{
    Structure p = (Structure)malloc(sizeof(struct Structure_));
    p->field = fieldList;
    p->name = name;
    return p;
}

FieldList CreateFieldHead()
{
    FieldList p = (FieldList)malloc(sizeof(struct FieldList_));
    p->name = NULL;
    p->tail = NULL;
    p->type = NULL;
    return p;
}
void CreateFieldNode(FieldList head, char *name, Type type)
{
    FieldList p = (FieldList)malloc(sizeof(struct FieldList_));
    FieldList q = head;
    p->name = (char *)malloc(strlen(name));
    strcpy(p->name, name);
    p->type = type;
    p->tail = NULL;
    while (q->tail != NULL)
        q = q->tail;
    q->tail = p;
    return;
}

Para CreateParaHead()
{
    Para p = (Para)malloc(sizeof(struct Para_));
    p->tail = NULL;
    p->type = NULL;
    return p;
}
void CreateParaNode(Para head, Type type)
{
    Para p = (Para)malloc(sizeof(struct Para_));
    Para q = head;
    p->type = type;
    p->tail = NULL;
    while (q->tail != NULL)
        q = q->tail;
    q->tail = p;
    return;
}

Func CreateFunc(int paramnum, Type ret, Para head)
{
    Func p = (Func)malloc(sizeof(struct Func_));
    p->paranum = paramnum;
    p->ret = ret;
    p->para = head;
    return p;
}

Symbol CreateSymbolVar(char *name, Type var, int beStru)
{
    Symbol p = (Symbol)malloc(sizeof(struct Symbol_));
    p->kind = VAR;
    p->name = (char *)malloc(strlen(name));
    strcpy(p->name, name);
    p->u.var = var;
    p->beStru = beStru;
    return p;
}

Symbol CreateSymbolFunc(char *name, Func func)
{
    Symbol p = (Symbol)malloc(sizeof(struct Symbol_));
    p->kind = FUNC;
    p->name = (char *)malloc(strlen(name));
    strcpy(p->name, name);
    p->u.func = func;
    return p;
}

Symbol CreateSymbolStru(char *name, Type structure)
{
    Symbol p = (Symbol)malloc(sizeof(struct Symbol_));
    p->kind = STRU;
    p->name = (char *)malloc(strlen(name));
    strcpy(p->name, name);
    p->u.structure = structure;
    return p;
}
